package com.zxjbyte.yiyi.framework.oss.storage.db;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.crypto.digest.DigestUtil;
import com.zxjbyte.yiyi.framework.oss.factory.OssConfigFactory;
import com.zxjbyte.yiyi.framework.oss.rule.OssRule;
import com.zxjbyte.yiyi.framework.oss.storage.AbstractOssTemplate;
import com.zxjbyte.yiyi.framework.oss.storage.FileMetadata;
import com.zxjbyte.yiyi.framework.oss.storage.OssPutResult;
import com.zxjbyte.yiyi.module.system.api.oss.OssFileApi;
import com.zxjbyte.yiyi.module.system.domain.dto.OssFileAddDTO;
import com.zxjbyte.yiyi.module.system.domain.result.OssFileResult;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.multipart.MultipartFile;

import java.io.InputStream;

/**
 * 数据库存储器模板类（生产不推荐）
 *
 * @Author zhangxingjia
 * @Date 2023/5/9 17:58
 * @Version: 1.0
 */
@Slf4j
@RequiredArgsConstructor
public class DbOssTemplate extends AbstractOssTemplate implements DbOssOperations{

    private final OssConfigFactory factory;
    private final OssRule ossRule;
    private final OssFileApi ossFileApi;
    private DbOssConfig config;

    private void init(){
        DbOssConfigWrapper wrapper = factory.getDbOssConfig();
        config = wrapper.getConfig();
    }

    @Override
    public FileMetadata statFile(String path) {
        OssFileResult model = ossFileApi.getContent(path);
        if(model == null || model.getContent() == null){
            return null;
        }
        FileMetadata metadata = new FileMetadata();
        metadata.setFileContent(model.getContent());
        metadata.setLength(model.getContent().length);
        metadata.setPutTime(model.getCreateTime());
        metadata.setName(path);
        metadata.setLink(formatGetFileUrl(config.getDomain(), path));
        metadata.setContentType(FileUtil.getMimeType(path));
        metadata.setHash(DigestUtil.sha256Hex(model.getContent()));
        return metadata;
    }

    @Override
    public OssPutResult putFile(InputStream input, String fileName) {
        // 此方法读取完毕之后会关闭流
        byte[] bytes = IoUtil.readBytes(input);
        return putFile(bytes, fileName);
    }

    @Override
    public OssPutResult putFile(byte[] content, String fileName) {
        return put(content, fileName);
    }

    @Override
    @SneakyThrows
    public OssPutResult putFile(MultipartFile file, String fileName) {
        return putFile(file.getInputStream(), fileName);
    }

    @Override
    public OssPutResult putFile(MultipartFile file) {
        return putFile(file, file.getOriginalFilename());
    }

    private OssPutResult put(byte[] content, String originalName){
        String path = ossRule.fileNameByTenant(originalName);
        OssFileAddDTO dto = new OssFileAddDTO();
        dto.setContent(content);
        dto.setPath(path);
        ossFileApi.addFile(dto);
        OssPutResult result = new OssPutResult();
        result.setOriginalName(originalName);
        result.setName(path);
        result.setDomain(config.getDomain());
        result.setLink(formatGetFileUrl(config.getDomain(), path));
        ossRecordAddPublish(result, content.length, "db");
        return result;
    }

    @Override
    public boolean deleteFile(String path) {
        boolean delResult = ossFileApi.deleteByPath(path);
        log.debug("DB Storage Execution Delete Files, current path: {}, execution result: {}", path, delResult);
        // 存储文件被删除之后删除日志记录（逻辑删除）
        ossRecordDeletePublish(path);
        return delResult;
    }

}
